home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / tclX6.4c / dist / tclsrc / help.tcl < prev    next >
Encoding:
Text File  |  1992-11-07  |  7.7 KB  |  260 lines

  1. #
  2. # help.tcl --
  3. #
  4. # Tcl help command. (see TclX manual)
  5. #------------------------------------------------------------------------------
  6. # Copyright 1992 Karl Lehenbauer and Mark Diekhans.
  7. #
  8. # Permission to use, copy, modify, and distribute this software and its
  9. # documentation for any purpose and without fee is hereby granted, provided
  10. # that the above copyright notice appear in all copies.  Karl Lehenbauer and
  11. # Mark Diekhans make no representations about the suitability of this
  12. # software for any purpose.  It is provided "as is" without express or
  13. # implied warranty.
  14. #------------------------------------------------------------------------------
  15. # $Id: help.tcl,v 2.0 1992/10/16 04:52:01 markd Rel $
  16. #------------------------------------------------------------------------------
  17. #
  18.  
  19. #@package: TclX-help help helpcd helppwd apropos
  20.  
  21. #------------------------------------------------------------------------------
  22. # Take a path name which might have . and .. elements and flatten them out.
  23.  
  24. proc help:flattenPath {pathName} {
  25.     set newPath {}
  26.     foreach element [split $pathName /] {
  27.         if {"$element" == "."} {
  28.            continue
  29.         }
  30.         if {"$element" == ".."} {
  31.             if {[llength [join $newPath /]] == 0} {
  32.                 error "Help: name goes above subject directory root"}
  33.             lvarpop newPath [expr [llength $newPath]-1]
  34.             continue
  35.         }
  36.         lappend newPath $element
  37.     }
  38.     set newPath [join $newPath /]
  39.     
  40.     # Take care of the case where we started with something line "/" or "/."
  41.  
  42.     if {("$newPath" == "") && [string match "/*" $pathName]} {
  43.         set newPath "/"}
  44.         
  45.     return $newPath
  46. }
  47.  
  48. #------------------------------------------------------------------------------
  49. # Take the help current directory and a path and evaluate it into a help root-
  50. # based path name.
  51.  
  52. proc help:EvalPath {pathName} {
  53.     global TCLENV
  54.  
  55.     if {![string match "/*" $pathName]} {
  56.         if {"$pathName" == ""} {
  57.             return $TCLENV(help:curDir)}
  58.         if {"$TCLENV(help:curDir)" == "/"} {
  59.             set pathName "/$pathName"
  60.         } else {
  61.             set pathName "$TCLENV(help:curDir)/$pathName"
  62.         }
  63.     }
  64.     set pathName [help:flattenPath $pathName]
  65.     if {[string match "*/" $pathName] && ($pathName != "/")} {
  66.         set pathName [csubstr $pathName 0 [expr [length $pathName]-1]]}
  67.  
  68.     return $pathName    
  69. }
  70.  
  71. #------------------------------------------------------------------------------
  72. # Display a line of output, pausing waiting for input before displaying if the
  73. # screen size has been reached.  Return 1 if output is to continue, return
  74. # 0 if no more should be outputed, indicated by input other than return.
  75. #
  76.  
  77. proc help:Display {line} {
  78.     global TCLENV
  79.     if {$TCLENV(help:lineCnt) >= 23} {
  80.         set TCLENV(help:lineCnt) 0
  81.         puts stdout ":" nonewline
  82.         flush stdout
  83.         gets stdin response
  84.         if {![lempty $response]} {
  85.             return 0}
  86.     }
  87.     puts stdout $line
  88.     incr TCLENV(help:lineCnt)
  89. }
  90.  
  91. #------------------------------------------------------------------------------
  92. # Display a file.
  93.  
  94. proc help:DisplayFile {filepath} {
  95.  
  96.     set inFH [open $filepath r]
  97.     while {[gets $inFH fileBuf] >= 0} {
  98.         if {![help:Display $fileBuf]} {
  99.             break}
  100.     }
  101.     close $inFH
  102.  
  103. }    
  104.  
  105. #------------------------------------------------------------------------------
  106. # Procedure to return contents of a directory.  A list is returned, consisting
  107. # of two lists.  The first list are all the directories (subjects) in the
  108. # specified directory.  The second is all of the help files.  Eash sub-list
  109. # is sorted in alphabetical order.
  110. #
  111.  
  112. proc help:ListDir {dirPath} {
  113.     set dirList {}
  114.     set fileList {}
  115.     if {[catch {set dirFiles [glob $dirPath/*]}] != 0} {
  116.         error "No files in subject directory: $dirPath"}
  117.     foreach fileName $dirFiles {
  118.         if [file isdirectory $fileName] {
  119.             lappend dirList "[file tail $fileName]/"
  120.         } else {
  121.             lappend fileList [file tail $fileName]
  122.         }
  123.     }
  124.    return [list [lsort $dirList] [lsort $fileList]]
  125. }
  126.  
  127. #------------------------------------------------------------------------------
  128. # Display a list of file names in a column format. This use columns of 14 
  129. # characters 3 blanks.
  130.  
  131. proc help:DisplayColumns {nameList} {
  132.     set count 0
  133.     set outLine ""
  134.     foreach name $nameList {
  135.         if {$count == 0} {
  136.             append outLine "   "}
  137.         append outLine $name
  138.         if {[incr count] < 4} {
  139.             set padLen [expr 17-[clength $name]]
  140.             if {$padLen < 3} {
  141.                set padLen 3}
  142.             append outLine [replicate " " $padLen]
  143.         } else {
  144.            if {![help:Display $outLine]} {
  145.                return}
  146.            set outLine ""
  147.            set count 0
  148.         }
  149.     }
  150.     if {$count != 0} {
  151.         help:Display $outLine}
  152.     return
  153. }
  154.  
  155.  
  156. #------------------------------------------------------------------------------
  157. # Help command main.
  158.  
  159. proc help {{subject {}}} {
  160.     global TCLENV
  161.  
  162.     set TCLENV(help:lineCnt) 0
  163.  
  164.     # Special case "help help", so we can get it at any level.
  165.  
  166.     if {($subject == "help") || ($subject == "?")} {
  167.         help:DisplayFile "$TCLENV(help:root)/help"
  168.         return
  169.     }
  170.  
  171.     set request [help:EvalPath $subject]
  172.     set requestPath "$TCLENV(help:root)$request"
  173.  
  174.     if {![file exists $requestPath]} {
  175.         error "Help:\"$request\" does not exist"}
  176.     
  177.     if [file isdirectory $requestPath] {
  178.         set dirList [help:ListDir $requestPath]
  179.         set subList  [lindex $dirList 0]
  180.         set fileList [lindex $dirList 1]
  181.         if {[llength $subList] != 0} {
  182.             help:Display "\nSubjects available in $request:"
  183.             help:DisplayColumns $subList
  184.         }
  185.         if {[llength $fileList] != 0} {
  186.             help:Display "\nHelp files available in $request:"
  187.             help:DisplayColumns $fileList
  188.         }
  189.     } else {
  190.         help:DisplayFile $requestPath
  191.     }
  192.     return
  193. }
  194.  
  195.  
  196. #------------------------------------------------------------------------------
  197. # Helpcd main.
  198. #   
  199. # The name of the new current directory is assembled from the current 
  200. # directory and the argument.  The name will be flatten and any trailing
  201. # "/" will be removed, unless the name is just "/".
  202.  
  203. proc helpcd {{dir /}} {
  204.     global TCLENV
  205.  
  206.     set request [help:EvalPath $dir]
  207.     set requestPath "$TCLENV(help:root)$request"
  208.  
  209.     if {![file exists $requestPath]} {
  210.         error "Helpcd: \"$request\" does not exist"}
  211.     
  212.     if {![file isdirectory $requestPath]} {
  213.         error "Helpcd: \"$request\" is not a directory"}
  214.  
  215.     set TCLENV(help:curDir) $request
  216.     return    
  217. }
  218.  
  219. #------------------------------------------------------------------------------
  220. # Helpcd main.
  221.  
  222. proc helppwd {} {
  223.         global TCLENV
  224.         echo "Current help subject directory: $TCLENV(help:curDir)"
  225. }
  226.  
  227. #==============================================================================
  228. #     Tcl apropos command.  (see Tcl shell manual)
  229. #------------------------------------------------------------------------------
  230.  
  231. proc apropos {name} {
  232.     global TCLENV
  233.  
  234.     set TCLENV(help:lineCnt) 0
  235.  
  236.     set aproposCT [scancontext create]
  237.     scanmatch -nocase $aproposCT $name {
  238.         set path [lindex $matchInfo(line) 0]
  239.         set desc [lrange $matchInfo(line) 1 end]
  240.         if {![help:Display [format "%s - %s" $path $desc]]} {
  241.             return}
  242.     }
  243.     foreach brief [glob -nocomplain $TCLENV(help:root)/*.brf] {
  244.         set briefFH [open $brief]
  245.         scanfile $aproposCT $briefFH
  246.         close $briefFH
  247.     }
  248.     scancontext delete $aproposCT
  249. }
  250.  
  251. #------------------------------------------------------------------------------
  252. # One time initialization done when the file is sourced.
  253. #
  254. global TCLENV TCLPATH
  255.  
  256. set TCLENV(help:root) [searchpath $TCLPATH help]
  257. set TCLENV(help:curDir) "/"
  258. set TCLENV(help:outBuf) {}
  259.